//
//  ViewController.m
//  RunTime的一些深入
//
//  Created by ZhouFahong on 16/7/22.
//  Copyright © 2016年 ZhouFahong. All rights reserved.
//

#import "ViewController.h"
#import "objc/runtime.h"
#import "MyViewController.h"

@interface ViewController ()

@end


// 函数 TestMetaClass
void TestMetaClass(id self,SEL _cmd){
    
    
    
    NSLog(@"This object is %p",self);
    
    NSLog(@"Class is %@, super class is %@",[self class],class_getSuperclass([self class]));
    
    
    
    Class currentClass = [self class];
    
    for (int i = 0; i < 4; i++) {
        NSLog(@"Following the isa pointer %d times gives %p", i ,currentClass);
        
        currentClass = objc_getClass((__bridge void *)currentClass);
        
    }
    
    NSLog(@"NSObject's class is %p", [NSObject class]);
    
    NSLog(@"NSObject's meta class is %p", objc_getClass((__bridge void *)[NSObject class]));
    
    
}


void FuntionTest(id self , SEL _cmd){
    NSLog(@"\n hello  world!");
}

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self ex_registerClassPair];
    
   NSLog(@"递归算法：%lf", [self digui:4]);
    
    
    UIButton *btn = [[UIButton alloc]initWithFrame:CGRectMake(50, 100, 50, 50)];
    [btn setBackgroundColor:[UIColor redColor]];
    [self.view addSubview:btn];
    
    [btn addTarget:self action:@selector(jump) forControlEvents:UIControlEventTouchUpInside];
    
    
    unsigned int outCount = 0;
    
    NSLog(@"获取指定类所在动态库");
    
    NSLog(@"UIView's Framework: %s", class_getImageName(NSClassFromString(@"UIView")));
    
    NSLog(@"获取指定库或框架中所有类的类名");
    const char ** classes = objc_copyClassNamesForImage(class_getImageName(NSClassFromString(@"UIView")), &outCount);
//    for (int i = 0; i < outCount; i++) {
//        NSLog(@"第%d个 class name: %s",i, classes[i]);
//    }
}

-(void)jump{
    
    MyViewController *myVC = [[MyViewController alloc]init];
    [self presentViewController:myVC animated:YES completion:^{
        
    }];
    
}

-(float)digui:(NSInteger)i{
    
    
    if (i == 0) {
        return 0;
    }else if (i == 1){
        return 1;
    }else if (i == 2){
        return 2;
    }else if (i > 2){
        
       return i * [self digui:i-1];
    }
    
    return 0;
}

//  1
//  运行时创建了一个NSError的 子类 TestClass
//  然后为这个子类添加一个方法testMetaClass
//  这个方法的实现是TestMetaClass函数
- (void)ex_registerClassPair {
    
    
    // 创建 类TestClass
    Class newClass = objc_allocateClassPair([NSString class], "TestClass", 0);
    
    // 添加类TestClass的方法 testMetaClass  这个方法通过函数 TestMetaClass 实现
    // IMP  实现一个带有 self 和 _cmd 为参数的函数 ------ TestMetaClass
    class_addMethod(newClass, @selector(testMetaClass), (IMP)TestMetaClass, "v@:");
    
    
    // 用 objc_registerClassPair 函数注册这个类,以便它能被别人使用
    objc_registerClassPair(newClass);
    
    
    // 创建 类的实例对象
//    id instance = [[newClass alloc] initWithDomain:@"some domain" code:0 userInfo:nil];
    id instance = [[newClass alloc]init];
    
    // 对象 调用 testMetaClass 方法
    [instance performSelector:@selector(testMetaClass)];
    
    // 版本信息相关
    class_setVersion(newClass,5);
    NSLog(@"version = %d",class_getVersion(newClass));
    
    NSLog(@"\n\n\n -----------分割线--------------\n\n\n");
    
    
    //  使用 NSInvocation 调用多个参数的方法
    
    
    
//    void(^myBlock)(int,int,int) = ^(int a,int b,int c){
//        NSLog(@"sum = %d",a+b+c);
//    };
//    __block int a = 1;
//    myBlock(a,a,a);
//    
//    
//    void (^aBlock)(int);
//    
//    aBlock(3);
    
//    class_addMethod(newClass, @selector(paraA:paraB:pataC:), imp_implementationWithBlock(^(int a,int b,int c){
//        NSLog(@"sum = %d",a+b+c);
//    }), "v@:");
    
    SEL myMethod = @selector(paraA:paraB:pataC:);
    NSMethodSignature *sig = [[self class] instanceMethodSignatureForSelector:myMethod];
    
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:sig];
    
    [invocation setSelector:myMethod];
    [invocation setTarget:self];
    
    int a = 1;
    int b = 2;
    int c = 3;
    [invocation setArgument:&a atIndex:2];
    [invocation setArgument:&b atIndex:3];
    [invocation setArgument:&c atIndex:4];
    
    [invocation invoke];
    
    
    
}



-(void)paraA:(int)a paraB:(int)b pataC:(int)c{
    
    
    NSLog(@"This object is %p",self);
    
    NSLog(@"Class is %@, super class is %@",[self class],[self superclass]);
    
    
    
    Class currentClass = [self class];
    
    for (int i = 0; i < 4; i++) {
        NSLog(@"Following the isa pointer %d times gives %p", i ,currentClass);
        
        currentClass = objc_getClass((__bridge void *)currentClass);
        
    }
    
    NSLog(@"NSObject's class is %p", [NSObject class]);
    
    NSLog(@"NSObject's meta class is %p", objc_getClass((__bridge void *)[NSObject class]));
    
    NSLog(@"a+b+c = %d",a+b+c);
    
}

// 2











@end
